//! HTTP网关插件
//! 
//! 提供REST API接口和中间件支持，包括请求路由、认证、限流、日志等功能

use std::sync::Arc;
use std::time::Duration;
use std::collections::HashMap;

use anyhow::{Result, anyhow};
use axum::{
    Router, Json,
    extract::{Path, State},
    response::{IntoResponse, Response},
    http::StatusCode,
    middleware::{self, Next},
    routing::{get, post},
};
use tower::ServiceBuilder;
use tower_http::{
    cors::CorsLayer,
    trace::TraceLayer,
    compression::CompressionLayer,
};
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use tokio::sync::RwLock;
use tracing::{info, debug, error};
use uuid::Uuid;
use chrono::{DateTime, Utc};

/// HTTP网关服务器
pub struct HttpGateway {
    /// 服务器配置
    config: HttpGatewayConfig,
    /// 路由状态
    state: Arc<GatewayState>,
}

/// HTTP网关配置
#[derive(Debug, Clone)]
pub struct HttpGatewayConfig {
    /// 监听地址
    pub host: String,
    /// 监听端口
    pub port: u16,
    /// 是否启用CORS
    pub enable_cors: bool,
    /// 是否启用压缩
    pub enable_compression: bool,
    /// 是否启用请求追踪
    pub enable_tracing: bool,
    /// 请求超时时间（秒）
    pub request_timeout: u64,
    /// 最大请求体大小（字节）
    pub max_request_size: usize,
    /// API版本前缀
    pub api_prefix: String,
}

impl Default for HttpGatewayConfig {
    fn default() -> Self {
        Self {
            host: "0.0.0.0".to_string(),
            port: 8080,
            enable_cors: true,
            enable_compression: true,
            enable_tracing: true,
            request_timeout: 30,
            max_request_size: 10 * 1024 * 1024, // 10MB
            api_prefix: "/api/v1".to_string(),
        }
    }
}

/// 网关状态
#[derive(Debug)]
pub struct GatewayState {
    /// 请求统计
    pub stats: Arc<RwLock<RequestStats>>,
    /// 数据源连接池
    pub datasources: Arc<RwLock<HashMap<String, DataSourceInfo>>>,
    /// 中间件配置
    pub middleware_config: Arc<RwLock<MiddlewareConfig>>,
}

/// 请求统计
#[derive(Debug, Default, Clone, Serialize)]
pub struct RequestStats {
    /// 总请求数
    pub total_requests: u64,
    /// 成功请求数
    pub successful_requests: u64,
    /// 失败请求数
    pub failed_requests: u64,
    /// 平均响应时间（毫秒）
    pub avg_response_time_ms: f64,
    /// 最后更新时间
    pub last_updated: Option<DateTime<Utc>>,
}

/// 数据源信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataSourceInfo {
    /// 数据源ID
    pub id: String,
    /// 数据源名称
    pub name: String,
    /// 数据源类型
    pub source_type: String,
    /// 连接状态
    pub status: String,
    /// 最后检查时间
    pub last_check: DateTime<Utc>,
}

/// 中间件配置
#[derive(Debug, Default, Clone)]
pub struct MiddlewareConfig {
    /// 是否启用认证
    pub enable_auth: bool,
    /// 是否启用限流
    pub enable_rate_limit: bool,
    /// 限流配置
    pub rate_limit_per_minute: u32,
}

/// SQL查询请求
#[derive(Debug, Serialize, Deserialize)]
pub struct SqlQueryRequest {
    /// SQL查询语句
    pub query: String,
    /// 数据源ID（可选）
    pub datasource: Option<String>,
    /// 查询参数（可选）
    pub parameters: Option<HashMap<String, Value>>,
}

/// 查询响应
#[derive(Debug, Serialize)]
pub struct QueryResponse {
    /// 请求ID
    pub request_id: String,
    /// 查询结果
    pub data: Value,
    /// 执行时间（毫秒）
    pub execution_time_ms: u64,
    /// 影响行数
    pub rows_affected: Option<u64>,
    /// 元数据
    pub metadata: QueryMetadata,
}

/// 查询元数据
#[derive(Debug, Serialize)]
pub struct QueryMetadata {
    /// 列信息
    pub columns: Vec<ColumnInfo>,
    /// 数据源信息
    pub datasource: String,
    /// 查询类型
    pub query_type: String,
}

/// 列信息
#[derive(Debug, Serialize)]
pub struct ColumnInfo {
    /// 列名
    pub name: String,
    /// 数据类型
    pub data_type: String,
    /// 是否可为空
    pub nullable: bool,
}

/// 错误响应
#[derive(Debug, Serialize)]
pub struct ErrorResponse {
    /// 错误代码
    pub error_code: String,
    /// 错误消息
    pub error_message: String,
    /// 请求ID
    pub request_id: String,
    /// 时间戳
    pub timestamp: DateTime<Utc>,
}

impl HttpGateway {
    /// 创建新的HTTP网关
    pub fn new(config: HttpGatewayConfig) -> Self {
        let state = Arc::new(GatewayState {
            stats: Arc::new(RwLock::new(RequestStats::default())),
            datasources: Arc::new(RwLock::new(HashMap::new())),
            middleware_config: Arc::new(RwLock::new(MiddlewareConfig::default())),
        });

        Self { config, state }
    }

    /// 构建路由器
    pub fn build_router(&self) -> Router {
        let mut router = Router::new()
            .route(&format!("{}/health", self.config.api_prefix), get(health_check))
            .route(&format!("{}/stats", self.config.api_prefix), get(get_stats))
            .route(&format!("{}/datasources", self.config.api_prefix), get(list_datasources))
            .route(&format!("{}/datasources/:id", self.config.api_prefix), get(get_datasource))
            .route(&format!("{}/query", self.config.api_prefix), post(execute_query))
            .route(&format!("{}/query/:datasource", self.config.api_prefix), post(execute_query_with_datasource))
            .with_state(self.state.clone());

        // 添加中间件
        let _service_builder = ServiceBuilder::new();

        if self.config.enable_tracing {
            router = router.layer(TraceLayer::new_for_http());
        }

        if self.config.enable_compression {
            router = router.layer(CompressionLayer::new());
        }

        if self.config.enable_cors {
            router = router.layer(CorsLayer::permissive());
        }

        // 添加请求统计中间件
        router = router.layer(middleware::from_fn_with_state(
            self.state.clone(),
            request_stats_middleware,
        ));

        router
    }

    /// 启动HTTP服务器
    pub async fn start(&self) -> Result<()> {
        let app = self.build_router();
        let addr = format!("{}:{}", self.config.host, self.config.port);
        
        info!("HTTP网关启动，监听地址: {}", addr);
        info!("API前缀: {}", self.config.api_prefix);
        
        let listener = tokio::net::TcpListener::bind(&addr).await
            .map_err(|e| anyhow!("绑定地址失败: {}", e))?;

        axum::serve(listener, app).await
            .map_err(|e| anyhow!("HTTP服务器启动失败: {}", e))?;

        Ok(())
    }

    /// 添加数据源
    pub async fn add_datasource(&self, datasource: DataSourceInfo) -> Result<()> {
        let mut datasources = self.state.datasources.write().await;
        datasources.insert(datasource.id.clone(), datasource);
        Ok(())
    }

    /// 移除数据源
    pub async fn remove_datasource(&self, id: &str) -> Result<()> {
        let mut datasources = self.state.datasources.write().await;
        datasources.remove(id);
        Ok(())
    }

    /// 获取请求统计
    pub async fn get_stats(&self) -> RequestStats {
        self.state.stats.read().await.clone()
    }
}

/// 健康检查处理器
async fn health_check() -> impl IntoResponse {
    Json(json!({
        "status": "healthy",
        "timestamp": Utc::now(),
        "version": "0.1.0"
    }))
}

/// 获取统计信息处理器
async fn get_stats(State(state): State<Arc<GatewayState>>) -> impl IntoResponse {
    let stats = state.stats.read().await.clone();
    Json(stats)
}

/// 列出数据源处理器
async fn list_datasources(State(state): State<Arc<GatewayState>>) -> impl IntoResponse {
    let datasources = state.datasources.read().await;
    let datasource_list: Vec<DataSourceInfo> = datasources.values().cloned().collect();
    Json(datasource_list)
}

/// 获取单个数据源处理器
async fn get_datasource(
    Path(id): Path<String>,
    State(state): State<Arc<GatewayState>>,
) -> impl IntoResponse {
    let datasources = state.datasources.read().await;
    
    match datasources.get(&id) {
        Some(datasource) => Json(datasource.clone()).into_response(),
        None => (
            StatusCode::NOT_FOUND,
            Json(ErrorResponse {
                error_code: "DATASOURCE_NOT_FOUND".to_string(),
                error_message: format!("数据源 {} 不存在", id),
                request_id: Uuid::new_v4().to_string(),
                timestamp: Utc::now(),
            }),
        ).into_response(),
    }
}

/// 执行查询处理器
async fn execute_query(
    State(state): State<Arc<GatewayState>>,
    Json(request): Json<SqlQueryRequest>,
) -> impl IntoResponse {
    let request_id = Uuid::new_v4().to_string();
    let start_time = std::time::Instant::now();

    debug!("执行SQL查询，请求ID: {}, SQL: {}", request_id, request.query);

    // 模拟查询执行
    let result = simulate_query_execution(&request).await;
    let execution_time = start_time.elapsed().as_millis() as u64;

    match result {
        Ok(data) => {
            let response = QueryResponse {
                request_id,
                data,
                execution_time_ms: execution_time,
                rows_affected: Some(1),
                metadata: QueryMetadata {
                    columns: vec![
                        ColumnInfo {
                            name: "result".to_string(),
                            data_type: "string".to_string(),
                            nullable: false,
                        }
                    ],
                    datasource: request.datasource.unwrap_or_else(|| "default".to_string()),
                    query_type: "SELECT".to_string(),
                },
            };
            Json(response).into_response()
        }
        Err(e) => {
            error!("查询执行失败，请求ID: {}, 错误: {}", request_id, e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ErrorResponse {
                    error_code: "QUERY_EXECUTION_ERROR".to_string(),
                    error_message: e.to_string(),
                    request_id,
                    timestamp: Utc::now(),
                }),
            ).into_response()
        }
    }
}

/// 带数据源的查询处理器
async fn execute_query_with_datasource(
    Path(datasource): Path<String>,
    State(state): State<Arc<GatewayState>>,
    Json(mut request): Json<SqlQueryRequest>,
) -> impl IntoResponse {
    // 设置数据源
    request.datasource = Some(datasource);
    execute_query(State(state), Json(request)).await
}

/// 请求统计中间件
async fn request_stats_middleware(
    State(state): State<Arc<GatewayState>>,
    request: axum::extract::Request,
    next: Next,
) -> Response {
    let start_time = std::time::Instant::now();
    
    // 执行请求
    let response = next.run(request).await;
    
    // 更新统计
    let duration = start_time.elapsed();
    let mut stats = state.stats.write().await;
    stats.total_requests += 1;
    
    if response.status().is_success() {
        stats.successful_requests += 1;
    } else {
        stats.failed_requests += 1;
    }
    
    // 更新平均响应时间
    let current_avg = stats.avg_response_time_ms;
    let new_time = duration.as_millis() as f64;
    stats.avg_response_time_ms = if stats.total_requests == 1 {
        new_time
    } else {
        (current_avg * (stats.total_requests - 1) as f64 + new_time) / stats.total_requests as f64
    };
    
    stats.last_updated = Some(Utc::now());
    
    response
}

/// 模拟查询执行
async fn simulate_query_execution(request: &SqlQueryRequest) -> Result<Value> {
    // 简单的查询模拟
    tokio::time::sleep(Duration::from_millis(10)).await;

    if request.query.to_lowercase().contains("error") {
        return Err(anyhow!("模拟查询错误"));
    }

    Ok(json!({
        "message": "查询执行成功",
        "query": request.query,
        "datasource": request.datasource.as_ref().unwrap_or(&"default".to_string()),
        "timestamp": Utc::now()
    }))
}

#[cfg(test)]
mod tests {
    use super::*;
    use axum::http::{Request, StatusCode};
    use tower::ServiceExt;
    use serde_json::json;

    #[tokio::test]
    async fn test_http_gateway_creation() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config.clone());

        assert_eq!(gateway.config.host, "0.0.0.0");
        assert_eq!(gateway.config.port, 8080);
        assert_eq!(gateway.config.api_prefix, "/api/v1");
        assert!(gateway.config.enable_cors);
        assert!(gateway.config.enable_compression);
        assert!(gateway.config.enable_tracing);
    }

    #[tokio::test]
    async fn test_http_gateway_config_custom() {
        let config = HttpGatewayConfig {
            host: "127.0.0.1".to_string(),
            port: 9090,
            enable_cors: false,
            enable_compression: false,
            enable_tracing: false,
            request_timeout: 60,
            max_request_size: 5 * 1024 * 1024,
            api_prefix: "/api/v2".to_string(),
        };

        let gateway = HttpGateway::new(config.clone());

        assert_eq!(gateway.config.host, "127.0.0.1");
        assert_eq!(gateway.config.port, 9090);
        assert_eq!(gateway.config.api_prefix, "/api/v2");
        assert!(!gateway.config.enable_cors);
        assert!(!gateway.config.enable_compression);
        assert!(!gateway.config.enable_tracing);
        assert_eq!(gateway.config.request_timeout, 60);
        assert_eq!(gateway.config.max_request_size, 5 * 1024 * 1024);
    }

    #[tokio::test]
    async fn test_health_check_endpoint() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);
        let app = gateway.build_router();

        let request = Request::builder()
            .uri("/api/v1/health")
            .body(axum::body::Body::empty())
            .unwrap();

        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_stats_endpoint() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);
        let app = gateway.build_router();

        let request = Request::builder()
            .uri("/api/v1/stats")
            .body(axum::body::Body::empty())
            .unwrap();

        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_datasources_endpoint() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);
        let app = gateway.build_router();

        let request = Request::builder()
            .uri("/api/v1/datasources")
            .body(axum::body::Body::empty())
            .unwrap();

        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_query_endpoint() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);
        let app = gateway.build_router();

        let query_request = SqlQueryRequest {
            query: "SELECT * FROM users".to_string(),
            datasource: Some("test_db".to_string()),
            parameters: None,
        };

        let request = Request::builder()
            .uri("/api/v1/query")
            .method("POST")
            .header("content-type", "application/json")
            .body(axum::body::Body::from(serde_json::to_string(&query_request).unwrap()))
            .unwrap();

        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_query_with_datasource_endpoint() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);
        let app = gateway.build_router();

        let query_request = SqlQueryRequest {
            query: "SELECT COUNT(*) FROM products".to_string(),
            datasource: None,
            parameters: None,
        };

        let request = Request::builder()
            .uri("/api/v1/query/mysql_db")
            .method("POST")
            .header("content-type", "application/json")
            .body(axum::body::Body::from(serde_json::to_string(&query_request).unwrap()))
            .unwrap();

        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_datasource_management() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);

        let datasource = DataSourceInfo {
            id: "test_db".to_string(),
            name: "Test Database".to_string(),
            source_type: "mysql".to_string(),
            status: "connected".to_string(),
            last_check: Utc::now(),
        };

        // 添加数据源
        gateway.add_datasource(datasource.clone()).await.unwrap();

        // 验证数据源已添加
        let datasources = gateway.state.datasources.read().await;
        assert!(datasources.contains_key("test_db"));
        assert_eq!(datasources.get("test_db").unwrap().name, "Test Database");

        drop(datasources);

        // 移除数据源
        gateway.remove_datasource("test_db").await.unwrap();

        // 验证数据源已移除
        let datasources = gateway.state.datasources.read().await;
        assert!(!datasources.contains_key("test_db"));
    }

    #[tokio::test]
    async fn test_request_stats() {
        let config = HttpGatewayConfig::default();
        let gateway = HttpGateway::new(config);

        // 初始统计应该为空
        let initial_stats = gateway.get_stats().await;
        assert_eq!(initial_stats.total_requests, 0);
        assert_eq!(initial_stats.successful_requests, 0);
        assert_eq!(initial_stats.failed_requests, 0);
    }

    #[tokio::test]
    async fn test_sql_query_request_serialization() {
        let request = SqlQueryRequest {
            query: "SELECT * FROM users WHERE age > 18".to_string(),
            datasource: Some("postgres_db".to_string()),
            parameters: Some({
                let mut params = HashMap::new();
                params.insert("limit".to_string(), json!(100));
                params.insert("offset".to_string(), json!(0));
                params
            }),
        };

        let json_str = serde_json::to_string(&request).unwrap();
        assert!(json_str.contains("SELECT * FROM users WHERE age > 18"));
        assert!(json_str.contains("postgres_db"));
        assert!(json_str.contains("limit"));
        assert!(json_str.contains("offset"));
    }

    #[tokio::test]
    async fn test_error_response_structure() {
        let error_response = ErrorResponse {
            error_code: "INVALID_QUERY".to_string(),
            error_message: "SQL语法错误".to_string(),
            request_id: "test-request-123".to_string(),
            timestamp: Utc::now(),
        };

        let json_str = serde_json::to_string(&error_response).unwrap();
        assert!(json_str.contains("INVALID_QUERY"));
        assert!(json_str.contains("SQL语法错误"));
        assert!(json_str.contains("test-request-123"));
    }

    #[tokio::test]
    async fn test_middleware_config() {
        let config = MiddlewareConfig {
            enable_auth: true,
            enable_rate_limit: true,
            rate_limit_per_minute: 100,
        };

        assert!(config.enable_auth);
        assert!(config.enable_rate_limit);
        assert_eq!(config.rate_limit_per_minute, 100);
    }

    #[tokio::test]
    async fn test_column_info_structure() {
        let column = ColumnInfo {
            name: "user_id".to_string(),
            data_type: "bigint".to_string(),
            nullable: false,
        };

        assert_eq!(column.name, "user_id");
        assert_eq!(column.data_type, "bigint");
        assert!(!column.nullable);
    }

    #[tokio::test]
    async fn test_simulate_query_execution() {
        // 测试成功查询
        let request = SqlQueryRequest {
            query: "SELECT * FROM users".to_string(),
            datasource: Some("test_db".to_string()),
            parameters: None,
        };

        let result = simulate_query_execution(&request).await;
        assert!(result.is_ok());

        let data = result.unwrap();
        assert!(data.get("message").is_some());
        assert!(data.get("query").is_some());
        assert!(data.get("datasource").is_some());

        // 测试错误查询
        let error_request = SqlQueryRequest {
            query: "SELECT * FROM error_table".to_string(),
            datasource: Some("test_db".to_string()),
            parameters: None,
        };

        let error_result = simulate_query_execution(&error_request).await;
        assert!(error_result.is_err());
    }
}
